package com.yunti.springboot.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.spire.doc.*;
import com.spire.doc.documents.*;
import com.yunti.springboot.commonenum.SemesterEnum;
import com.yunti.springboot.po.School;
import com.yunti.springboot.po.Student;
import com.yunti.springboot.vo.req.ScoreCollectReq;
import com.yunti.springboot.vo.req.ScoreTableReq;
import com.yunti.springboot.vo.res.StuExamAndScoreInfoRes;
import com.yunti.springboot.vo.res.StuExamInfo;
import com.yunti.springboot.vo.res.StudentVo;
import freemarker.template.Configuration;
import freemarker.template.Version;
import org.springframework.core.io.ClassPathResource;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 成绩单生成工具类
 * @author yaming
 */
public class ScoreWordUtil {

    public synchronized static Document buildPrintScore(StuExamAndScoreInfoRes stuExamAndScoreInfoRes) throws IOException, WriterException {
        Student student = stuExamAndScoreInfoRes.getStudent();
        School school = stuExamAndScoreInfoRes.getSchool();
        ClassPathResource classPathResource = new ClassPathResource("/ftl/scoreDocTemplate.docx");
        InputStream inputStream = classPathResource.getInputStream();
        Document doc = new Document();
        doc.loadFromStream(inputStream,FileFormat.Docx);
        //获取第一节
        Section section = doc.getSections().get(0);
        //获取第一个表格
        Table table = section.getTables().get(0);
        int startCellIndex = 2;
        int secStartCellIndex = 2;



        List<StuExamInfo.StuExam> stuExamList = stuExamAndScoreInfoRes.getStuExamInfo().getStuExamList();
        List<Map<String,String>> stuScoreList = stuExamAndScoreInfoRes.getStuScoreInfo().getStuScoreList();

        int xkCellNum = 0;
        int zxClellNum = 0;
        int bxCellNum = 0;
        int jcCellNum = 0;

        table.getRows().get(1).getCells().get(2).getParagraphs().get(0).appendText(student.getName());
        table.getRows().get(1).getCells().get(2).getParagraphs().get(0).getFormat().setHorizontalAlignment(HorizontalAlignment.Center);

        table.getRows().get(1).getCells().get(6).getParagraphs().get(0).appendText(student.getSex() == 1?"男":"女");
        table.getRows().get(1).getCells().get(6).getParagraphs().get(0).getFormat().setHorizontalAlignment(HorizontalAlignment.Center);

        table.getRows().get(1).getCells().get(10).getParagraphs().get(0).appendText(student.getClassName());
        table.getRows().get(1).getCells().get(10).getParagraphs().get(0).getFormat().setHorizontalAlignment(HorizontalAlignment.Center);

        boolean haszxjn = false;
        boolean hasjctn = false;

        Map<Integer,List<StuExamInfo.StuExam>> stuExamMap = stuExamList.stream().collect(Collectors.groupingBy(StuExamInfo.StuExam::getType));
        for(StuExamInfo.StuExam stuExam : stuExamList){
            if(stuExam.getType() == 4)continue;

//            table.getRows().get(2).getCells().get(startCellIndex).getParagraphs().get(0).appendText(stuExam.getTittle());
            if (stuExam.getStuExamDetails() == null){
                continue;
            }
//            table.applyHorizontalMerge(2,startCellIndex,startCellIndex + stuExam.getStuExamDetails().size() - 1);
//            startCellIndex += stuExam.getStuExamDetails().size();

            if(stuExam.getType() == 1){
                table.getRows().get(2).getCells().get(startCellIndex).getParagraphs().get(0).appendText("必考项目");
                table.getRows().get(3).getCells().get(startCellIndex).getParagraphs().get(0).appendText(stuExam.getTittle());
                table.applyHorizontalMerge(2,startCellIndex,startCellIndex + stuExam.getStuExamDetails().size() - 1);
                table.applyHorizontalMerge(3,startCellIndex,startCellIndex + stuExam.getStuExamDetails().size() - 1);
                table.applyHorizontalMerge(4,startCellIndex,startCellIndex + stuExam.getStuExamDetails().size() - 1);
                table.applyVerticalMerge(2,3,4);

                bxCellNum += stuExam.getStuExamDetails().size();
            }

            if(stuExam.getType() == 2){
                table.getRows().get(3).getCells().get(startCellIndex).getParagraphs().get(0).appendText(stuExam.getTittle());
                table.applyHorizontalMerge(3,startCellIndex,startCellIndex + stuExam.getStuExamDetails().size() - 1);
                table.applyHorizontalMerge(4,startCellIndex,startCellIndex + stuExam.getStuExamDetails().size() - 1);
                table.applyVerticalMerge(5,3,4);
                jcCellNum += stuExam.getStuExamDetails().size();
                xkCellNum += stuExam.getStuExamDetails().size();
                hasjctn = true;
            }

            if(stuExam.getType() == 3){
                table.getRows().get(4).getCells().get(startCellIndex).getParagraphs().get(0).appendText(stuExam.getTittle());
                table.applyHorizontalMerge(4,startCellIndex,startCellIndex + stuExam.getStuExamDetails().size() - 1);

                xkCellNum += stuExam.getStuExamDetails().size();
                zxClellNum += stuExam.getStuExamDetails().size();
                haszxjn = true;
            }

            if(stuExam.getType() != 4){
                List<StuExamInfo.StuExamDetail> stuExamDetails = stuExam.getStuExamDetails();
                for(StuExamInfo.StuExamDetail stuExamDetail : stuExamDetails){
                    table.getRows().get(5).getCells().get(secStartCellIndex).getParagraphs().get(0).appendText(stuExamDetail.getTittle());
                    for (int i = 0; i < stuScoreList.size(); i++) {
                        Map<String,String> scoreMap = stuScoreList.get(i);
                        if (scoreMap.get(stuExamDetail.getKey()) != null){
                            table.getRows().get(6 + i).getCells().get(secStartCellIndex).getParagraphs().get(0).appendText(scoreMap.get(stuExamDetail.getKey()));
                        }
                    }
                    secStartCellIndex++;
                }
                startCellIndex+=stuExam.getStuExamDetails().size();

            }
        }

        List<StuExamInfo.StuExam> stuJkExam = stuExamMap.get(4);
        if(stuJkExam != null && stuJkExam.size() != 0){
            table.getRows().get(6).getCells().get(14).getParagraphs().get(0).appendText("体质健康监测");
            table.getRows().get(7).getCells().get(14).getParagraphs().get(0).appendText("身高");
            table.getRows().get(8).getCells().get(14).getParagraphs().get(0).appendText("体重");
            table.getRows().get(9).getCells().get(14).getParagraphs().get(0).appendText("肺活量");
            table.getRows().get(10).getCells().get(14).getParagraphs().get(0).appendText("BMI指数");
            table.getRows().get(12).getCells().get(14).getParagraphs().get(0).appendText("肺活量体重指数");
            table.applyHorizontalMerge( 6,14,15);
            table.applyHorizontalMerge( 10,14,15);
            table.applyHorizontalMerge( 11,14,15);
            table.applyHorizontalMerge( 12,14,15);
            table.applyHorizontalMerge( 13,14,15);
        }else {
            table.applyHorizontalMerge( 6,14,15);
            table.applyHorizontalMerge( 7,14,15);
            table.applyHorizontalMerge( 8,14,15);
            table.applyHorizontalMerge( 9,14,15);
            table.applyHorizontalMerge( 10,14,15);
            table.applyHorizontalMerge( 11,14,15);
            table.applyHorizontalMerge( 12,14,15);
            table.applyHorizontalMerge( 13,14,15);
            table.applyHorizontalMerge( 14,14,15);

            table.applyVerticalMerge(14,6,14);
        }



        if(hasjctn||haszxjn){
            table.getRows().get(2).getCells().get(2 + bxCellNum).addParagraph().appendText("选考项目");
            table.applyHorizontalMerge(2,2 + bxCellNum,2 + bxCellNum + xkCellNum - 1);
            table.getRows().get(2).getCells().get(2 + bxCellNum).getParagraphs().get(0).getFormat().setHorizontalAlignment(HorizontalAlignment.Center);

        }
        if(haszxjn){
            table.applyHorizontalMerge(3,2 + bxCellNum + jcCellNum,2 + bxCellNum  + xkCellNum - 1);
        }


        for (int i = 2; i < 15; i++) {
            table.applyHorizontalMerge(i,2 + bxCellNum + xkCellNum, 13);
        }
//
        table.applyVerticalMerge(2 + bxCellNum + xkCellNum,2,14);
        table.applyHorizontalMerge(15,0, 7);

//        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//        // 设置字符集编码
//        Map<EncodeHintType, Object> hints = new HashMap<>();
//        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
//        // 生成二维码矩阵
//        BitMatrix bitMatrix = new MultiFormatWriter().encode(student.getStuno(), BarcodeFormat.QR_CODE, 150, 150, hints);
//        // 写入文件
//        MatrixToImageWriter.writeToStream(bitMatrix, "png", byteArrayOutputStream);




        if(haszxjn){
            table.getRows().get(3).getCells().get(2 + bxCellNum + jcCellNum).addParagraph().appendText("专项技能选考");
            table.getRows().get(3).getCells().get(2 + bxCellNum + jcCellNum).getParagraphs().get(0).getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
        }

        table.getRows().get(0).getCells().get(0).getParagraphs().get(0).appendText(school.getName()+stuExamAndScoreInfoRes.getSemesterEnum().getMessage()+"体育中考成绩登记卡");
        table.getRows().get(0).getCells().get(0).getParagraphs().get(0).getFormat().setHorizontalAlignment(HorizontalAlignment.Center);


        table.getRows().get(5).setHeightType(TableRowHeightType.Exactly);
        table.getRows().get(5).setHeight(120);

        BufferedImage image = BarCodeUtils.getBarCodeWithWords(student.getStuNo(),
                "学号：" + student.getStuNo(),
                student.getClassName(),
                student.getName());

        BufferedImage image2 = RotateImageUtil.rotateImage(image,90);


        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        ImageIO.write(image2, "png", byteArrayOutputStream);


        byteArrayOutputStream = new ByteArrayOutputStream();
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 生成二维码矩阵
        BitMatrix bitMatrix = new MultiFormatWriter().encode(student.getStuNo(), BarcodeFormat.QR_CODE, 150, 150, hints);
        // 写入文件
        MatrixToImageWriter.writeToStream(bitMatrix, "png", byteArrayOutputStream);
//        table.getRows().get(1).getCells().get(0).addParagraph().appendPicture(byteArrayOutputStream.toByteArray());

        table.getRows().get(1).getCells().get(14).addParagraph().appendPicture(byteArrayOutputStream.toByteArray());




        //保存文档
//        doc.saveToFile("OutputScore.docx", FileFormat.Docx);
        return doc;
    }

    static void test() throws WriterException, IOException {
        //创建Document类的对象
        Document doc = new Document();
        Section sec = doc.addSection();
        sec.getPageSetup().setOrientation(PageOrientation.Landscape);

        //设置页边距
        sec.getPageSetup().getMargins().setTop(80f);
        sec.getPageSetup().getMargins().setBottom(80f);
        sec.getPageSetup().getMargins().setLeft(80f);
        sec.getPageSetup().getMargins().setRight(80f);

        //添加一个4行4列的表格
        Table tb= sec.addTable(true);
        tb.resetCells(15,14);

        //调用方法横向合并第1行中
        tb.applyHorizontalMerge(0,0,13);
        for (int i = 0; i < 15; i++) {
            tb.getRows().get(i).setHeight(26);
        }
        tb.getRows().get(0).getCells().get(0).addParagraph().appendText("昆明三中呈贡学校（呈贡一中）七年级上学期体育中考成绩单（12分）");

        //开始合并单元格
        //1.二维码位置
//        tb.applyHorizontalMerge(1,0,1);
//        tb.applyHorizontalMerge(2,0,1);
//        tb.applyHorizontalMerge(3,0,1);
//        tb.applyHorizontalMerge(4,0,1);
//        tb.applyHorizontalMerge(5,0,1);
        for (int i = 1; i < 15; i++) {
            tb.applyHorizontalMerge(i,0,1);
        }
        tb.applyVerticalMerge(0,1,5);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        // 设置字符集编码
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 生成二维码矩阵
        BitMatrix bitMatrix = new MultiFormatWriter().encode("2018118535138", BarcodeFormat.QR_CODE, 150, 150, hints);
        // 写入文件
        MatrixToImageWriter.writeToStream(bitMatrix, "png", outputStream);
        tb.getRows().get(1).getCells().get(0).addParagraph().appendPicture(outputStream.toByteArray());
        //2.第二行
        tb.applyHorizontalMerge(1,2,3);
        tb.applyHorizontalMerge(1,4,5);
        tb.applyHorizontalMerge(1,6,7);
        tb.applyHorizontalMerge(1,8,9);
        tb.applyHorizontalMerge(1,10,11);
        tb.applyHorizontalMerge(1,12,13);
        tb.getRows().get(1).getCells().get(2).addParagraph().appendText("姓名");
        tb.getRows().get(1).getCells().get(6).addParagraph().appendText("性别");
        tb.getRows().get(1).getCells().get(10).addParagraph().appendText("班级");

        //项目标题
        tb.applyVerticalMerge(2,2,5);
        tb.getRows().get(2).getCells().get(2).addParagraph().appendText("项目");
        //必考项目标题
        tb.applyHorizontalMerge(2,3,5);
        tb.getRows().get(2).getCells().get(3).addParagraph().appendText("必考项目");
        tb.applyVerticalMerge(3,3,5);
        tb.getRows().get(3).getCells().get(3).addParagraph().appendText("800/1000米");
        tb.applyVerticalMerge(4,3,5);
        tb.getRows().get(3).getCells().get(4).addParagraph().appendText("1分钟跳绳");
        tb.applyVerticalMerge(5,3,5);
        tb.getRows().get(3).getCells().get(5).addParagraph().appendText("50米跑");
        //体质健康

        tb.applyHorizontalMerge(2,6,8);
        tb.getRows().get(2).getCells().get(6).addParagraph().appendText("体质健康");
        tb.applyVerticalMerge(6,3,5);
        tb.getRows().get(3).getCells().get(6).addParagraph().appendText("身高");
        tb.applyVerticalMerge(7,3,5);
        tb.getRows().get(3).getCells().get(7).addParagraph().appendText("体重");
        tb.applyVerticalMerge(8,3,5);
        tb.getRows().get(3).getCells().get(8).addParagraph().appendText("肺活量");
        //

        for (int i = 2; i < 15; i++) {
            tb.applyHorizontalMerge(i,9,13);
        }

        tb.applyVerticalMerge(9,2,14);

        tb.getRows().get(6).getCells().get(0).addParagraph().appendText("第一次成绩");
        tb.getRows().get(7).getCells().get(0).addParagraph().appendText("得分");
        tb.getRows().get(8).getCells().get(0).addParagraph().appendText("教师签字");
        tb.getRows().get(9).getCells().get(0).addParagraph().appendText("第二次成绩");
        tb.getRows().get(10).getCells().get(0).addParagraph().appendText("得分");
        tb.getRows().get(11).getCells().get(0).addParagraph().appendText("教师签字");
        tb.getRows().get(12).getCells().get(0).addParagraph().appendText("第三次成绩");
        tb.getRows().get(13).getCells().get(0).addParagraph().appendText("得分");
        tb.getRows().get(14).getCells().get(0).addParagraph().appendText("教师签字");

//        tb.applyHorizontalMerge(1,3,13);
//        tb.getRows().get(1).getCells().get(3).splitCell(6,1);
        //结束合并

        //将表格居中对齐（或设置为靠左或靠右）

        tb.getTableFormat().setHorizontalAlignment(RowAlignment.Center);

        //保存文档
        doc.saveToFile("scoreDocTemplate.docx", FileFormat.Docx);
    }


    public static void buildTemplate(){
        try {
            //创建Document类的对象
            Document doc = new Document();
            Section sec = doc.addSection();

            sec.getPageSetup().setOrientation(PageOrientation.Landscape);

            //添加一个4行4列的表格
            Table tb= sec.addTable(true);
            tb.resetCells(16,16);

            for (int i = 0; i < 16; i++) {
                    for (int j = 0; j < 16; j++) {
                    tb.getRows().get(i).getCells().get(j).addParagraph();
                    tb.getRows().get(i).getCells().get(j).getParagraphs().get(0).getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
                    tb.getRows().get(i).getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);

                }
            }

//            tb.getRows().get(0).getCells().get(0).getParagraphs().get(0).appendText("昆明三中呈贡学校（呈贡一中）七年级上学期体育中考成绩单（12分）");


            //调用方法横向合并第1行中
            tb.applyHorizontalMerge(0,0,15);
            for (int i = 0; i < 16; i++) {
                tb.getRows().get(i).setHeight(26);
            }
            tb.setDefaultColumnWidth(110);

            tb.getRows().get(15).getCells().get(8).getParagraphs().get(0).appendText("家长签字：");
            tb.getRows().get(15).getCells().get(12).getParagraphs().get(0).appendText("学生签字：");



            tb.getRows().get(1).getCells().get(0).getParagraphs().get(0).appendText("姓名");
            tb.getRows().get(1).getCells().get(4).getParagraphs().get(0).appendText("性别");
            tb.getRows().get(1).getCells().get(8).getParagraphs().get(0).appendText("班级");

            tb.getRows().get(2).getCells().get(0).getParagraphs().get(0).appendText("类别");

            tb.getRows().get(5).getCells().get(0).getParagraphs().get(0).appendText("项目");

//            tb.getRows().get(1).getCells().get(14).getParagraphs().get(0).appendText("贴条形码处");

            tb.getRows().get(6).getCells().get(0).getParagraphs().get(0).appendText("第一次");
            tb.getRows().get(9).getCells().get(0).getParagraphs().get(0).appendText("第二次");
            tb.getRows().get(12).getCells().get(0).getParagraphs().get(0).appendText("第三次");


            tb.getRows().get(6).getCells().get(1).getParagraphs().get(0).appendText("成绩");
            tb.getRows().get(7).getCells().get(1).getParagraphs().get(0).appendText("得分");
            tb.getRows().get(8).getCells().get(1).getParagraphs().get(0).appendText("教师签字");

            tb.getRows().get(9).getCells().get(1).getParagraphs().get(0).appendText("成绩");
            tb.getRows().get(10).getCells().get(1).getParagraphs().get(0).appendText("得分");
            tb.getRows().get(11).getCells().get(1).getParagraphs().get(0).appendText("教师签字");

            tb.getRows().get(12).getCells().get(1).getParagraphs().get(0).appendText("成绩");
            tb.getRows().get(13).getCells().get(1).getParagraphs().get(0).appendText("得分");
            tb.getRows().get(14).getCells().get(1).getParagraphs().get(0).appendText("教师签字");




            tb.applyVerticalMerge(0,6,8);
            tb.applyVerticalMerge(0,9,11);
            tb.applyVerticalMerge(0,12,14);

            //合并第二行
            for (int i = 0; i < 8; i++) {
                tb.applyHorizontalMerge(1,0 + i * 2,1 + i * 2);
            }


            //合并类别
            for (int i = 0; i < 4; i++) {
                tb.applyHorizontalMerge(1 + i,0,1);
            }
            tb.applyVerticalMerge(0,2,4);
//
            //合并条形码处
            for (int i = 1; i < 6; i++) {
                tb.applyHorizontalMerge( i,14,15);
            }
            tb.applyVerticalMerge(14,1,5);

            tb.getRows().get(5).setHeightType(TableRowHeightType.Exactly);
            tb.getRows().get(5).setHeight(110);

            tb.applyHorizontalMerge( 5,0,1);
            tb.applyHorizontalMerge( 15,8,9);
            tb.applyHorizontalMerge( 15,10,11);
            tb.applyHorizontalMerge( 15,12,13);
            tb.applyHorizontalMerge( 15,14,15);
//

//

            //保存文档
            doc.saveToFile("scoreDocTemplate.docx", FileFormat.Docx_2013);



            //保存文档
//            doc.saveToFile("scoreDocTemplate.docx", FileFormat.Docx);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void getScoreTable(OutputStream stream, List<StudentVo> studentRes, String schoolName, ScoreCollectReq req) {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        Writer out = null;
        try {
            dataMap.put("schoolName", schoolName);
            dataMap.put("tableHead", "初中学生体育科目成绩表");
            if(SemesterEnum.七年上.getCode().equals(req.getSemester())||SemesterEnum.八年上.getCode().equals(req.getSemester())||SemesterEnum.九年上.getCode().equals(req.getSemester())){
                dataMap.put("examName", "50米");
                dataMap.put("subName", "1.引体向上(男)/1分钟仰卧起坐(女);" +
                        "2.坐位体前屈；3.200米游泳" +
                        "4.立定跳远；5.投掷实心球；      " +
                        "6.100米跑(6选2)");
            }else if(SemesterEnum.七年下.getCode().equals(req.getSemester())||SemesterEnum.八年下.getCode().equals(req.getSemester())||SemesterEnum.九年下.getCode().equals(req.getSemester())){
                dataMap.put("examName", "15米x4");
                dataMap.put("subName", "1.足球；2.篮球；" +
                        "3.排球；4.乒乓球；" +
                        "5.羽毛球；  6.网球；"+
                        "7.套路；8.散打(8选2)");
            }
            if (req.getType() != null){
                if(req.getType() == 1){
                    dataMap.put("subName", "1.引体向上(男)/1分钟仰卧起坐(女);" +
                            "2.坐位体前屈；3.200米游泳" +
                            "4.立定跳远；5.投掷实心球；      " +
                            "6.100米跑(6选2)");
                } else  if(req.getType() == 2) {
                    dataMap.put("subName", "1.足球；2.篮球；" +
                            "3.排球；4.乒乓球；" +
                            "5.羽毛球；  6.网球；"+
                            "7.套路；8.散打(8选2)");
                }
            }

            dataMap.put("list", studentRes);

            //Configuration 用于读取ftl文件
            Configuration configuration = new Configuration(new Version("2.3.0"));
            configuration.setDefaultEncoding("utf-8");
            //指定路径的第一种方式（根据某个类的相对路径指定）
            configuration.setClassForTemplateLoading(ScoreWordUtil.class, "/ftl/");
            //以utf-8的编码读取ftl文件
            freemarker.template.Template template = configuration.getTemplate("template_score.ftl", "utf-8");
            out = new BufferedWriter(new OutputStreamWriter(stream, "utf-8"), 10240);
            template.process(dataMap, out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Document buildPrintScoreByList(List<StuExamAndScoreInfoRes> scoreInfoResArrayList) throws IOException, WriterException {
        Document document = new Document();

        for (int i = 0; i < scoreInfoResArrayList.size(); i++) {
            Document document1 = buildPrintScore(scoreInfoResArrayList.get(i));
            document.addSection().getPageSetup().setOrientation(PageOrientation.Landscape);
            //在第二个文档中循环获取所有节
            for (Object sectionObj : (Iterable) document1.getSections()) {
                Section sec=(Section)sectionObj;
                //在所有节中循环获取所有子对象
                for (Object docObj :(Iterable ) sec.getBody().getChildObjects()) {
                    DocumentObject obj=(DocumentObject)docObj;

                    //获取第一个文档的最后一节
                    Section lastSection = document.getLastSection();

                    //将所有子对象添加到第一个文档的最后一节中
                    Body body = lastSection.getBody();
                    body.getChildObjects().add(obj.deepClone());
                }
            }
        }
        return document;
    }
}
